package com.biscuit.page.basicservice.design.verify_code.publish.factory;

import com.biscuit.page.basicservice.design.verify_code.publish.VerifyCodePublishType;
import com.biscuit.page.basicservice.design.verify_code.publish.VerifyCodePublishTypeEnum;
import com.biscuit.page.basicservice.design.verify_code.publish.strategy.AbstractVerifyCodePublishStrategy;
import com.biscuit.page.basicservice.utils.BaseExceptionUtil;
import lombok.Setter;
import org.springframework.beans.factory.InitializingBean;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author biscuit
 * @createTime 2024/6/25 11:04
 */
public class VerifyCodePublishStrategyFactory implements InitializingBean {

    @Setter
    private List<AbstractVerifyCodePublishStrategy> strategyList;

    private Map<VerifyCodePublishTypeEnum, AbstractVerifyCodePublishStrategy> strategyMap;

    @Override
    public void afterPropertiesSet() {
        // 集合大小初始化
        this.strategyMap = new HashMap<>(this.strategyList.size() << 1);

        // 过滤掉装饰者实现类不包含注解的超类，并将具体的装饰者实现类设置到集合中
        strategyList.stream()
                .filter(strategy -> {
                    VerifyCodePublishType annotation = strategy.getClass().getAnnotation(VerifyCodePublishType.class);
                    return Objects.nonNull(annotation);
                })
                .forEach(strategy -> {
                    VerifyCodePublishType annotation = strategy.getClass().getAnnotation(VerifyCodePublishType.class);
                    this.strategyMap.put(annotation.type(), strategy);
                });
    }

    public AbstractVerifyCodePublishStrategy create(int type) {
        VerifyCodePublishTypeEnum publishTypeEnum = VerifyCodePublishTypeEnum.getEnumByType(type);
        BaseExceptionUtil.throwException(Objects.nonNull(publishTypeEnum), "短信发送类型不存在");
        AbstractVerifyCodePublishStrategy strategy = this.strategyMap.get(publishTypeEnum);
        BaseExceptionUtil.throwException(Objects.nonNull(strategy), "短信发送类型装饰者实现类不存在");
        return strategy;
    }

}
